package com.xhlj.socket;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xhlj.controller.request_body.CommentBody;
import com.xhlj.entity.Comment;
import com.xhlj.service.CommentService;
import com.xhlj.utils.RedisKey;
import jakarta.annotation.Resource;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.CrossOrigin;

import java.util.*;

@Service

@ServerEndpoint("/saying")
public class WebSocketService {
    private String username;
    private Session session;
    /*WebSocket是多实例的，你要使用静态属性，把这个关联到类上才可以*/
    private static StringRedisTemplate stringRedisTemplate;
    private static CommentService commentService;

    @Autowired
    private void stringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        WebSocketService.stringRedisTemplate = stringRedisTemplate;
    }

    @Autowired
    private void commentService(CommentService commentService) {

        WebSocketService.commentService = commentService;
    }

    /*
     * 第一次客户端主动建立连接时会发送消息
     *   格式:websocket:reply:123456(username)
     * 然后我们直接记录到redis中:const:username: {commentId,isView}  表示内容和已读,用自带的哈希表存,方便统计次数
     * sendMessage()发送消息
     * deleteCommentInRedis(contentId)反正也没用了直接把这条记录删了
     * buildUnViewedList()根据redis的表把所有Comment找出来
     *
     * {
     *   type:1
     *   data:json(comment)/string(username)/string(commentId)
     * }
     * */
    void sendMessage(String message) {
        this.session.getAsyncRemote().sendText(message);
    }

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        this.session = session;
    }

    @OnMessage
    public void onMessage(String message, boolean last) {

        MessageFormat messageInfo = JSON.parseObject(message, MessageFormat.class);
        int type = messageInfo.getType();
        String data = messageInfo.getData();
        /*到时候把这个消息格式定下来*/
        if (MessageEnmu.TOPIC_USERNAME == MessageEnmu.fromValue(type)) {
            this.username = data;
            System.out.println(username);
        } else if (MessageEnmu.TOPIC_COMMENT_INSERT == MessageEnmu.fromValue(type)) {
            createCommentAndSave(data);
        } else if (MessageEnmu.TOPIC_GET_List == MessageEnmu.fromValue(type))
            buildUnViewedList();
        else if (MessageEnmu.TOPIC_COMMENT_READ == MessageEnmu.fromValue(type))
            deleteCommentInRedis(data);
    }

    private void createCommentAndSave(String data) {
        /*完成*/
        try {
            CommentBody body = JSON.parseObject(data, CommentBody.class);
            Comment comment = commentService.addComment(body);
            String key = RedisKey.Reply_prefix + this.username;
            /*一直到这都很OK
             * 在 Redis 中，HashMap 的 value 只能是字符串。
             * */
            ListOperations<String, String> ops = stringRedisTemplate.opsForList();
            String value = String.format("%s|%s", comment.getCommentId(), "0");
            ops.rightPush(key, value);
        } catch (Exception exception) {
            sendMessage("消息的json格式错误" + exception.getMessage());
        }
    }

    /*完成*/
    private void buildUnViewedList() {
        try {
            String key = RedisKey.Reply_prefix + this.username;
            Long size = stringRedisTemplate.opsForList().size(key);
            List<String> commentString = stringRedisTemplate.opsForList().range(key, 0, size - 1);
            ArrayList<Comment> comments = new ArrayList<>();
            for (String item : commentString) {
                String commentId = item.split("|")[0];
                String isView = item.split("|")[1];
                LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Comment::getCommentId, commentId);
                Comment one = commentService.getOne(wrapper);
                comments.add(one);
            }
            sendMessage(JSON.toJSONString(comments));
        } catch (Exception exception) {
            sendMessage("消息的json格式错误");
        }
    }
/*完成*/
    private void deleteCommentInRedis(String commentId) {
        try {
            String key = RedisKey.Reply_prefix + this.username;
            Long size = stringRedisTemplate.opsForList().size(key);
            ListOperations<String, String> ops = stringRedisTemplate.opsForList();
            List<String> commentString = ops.range(key, 0, size - 1);
            for (String item : commentString) {
                String id = item.substring(0, item.indexOf('|'));
                if (id.equals(commentId)) {
                    ops.remove(key, 1, item);
                }
            }
        } catch (Exception exception) {
            sendMessage("消息的json格式错误"+exception.getMessage());
            System.out.println(exception.getMessage());
        }
    }

    @OnClose
    public void onClose(CloseReason closeReason) {
        System.out.println("连接关闭");

    }
}
